import bpy
import struct 
from bpy.props import *

#chelive panel
class CheLiveObjectButtonsPanel(bpy.types.Panel):
	bl_space_type = "PROPERTIES"
	bl_region_type = "WINDOW"
	bl_context = "object"

class OBJECT_PT_CheLive(CheLiveObjectButtonsPanel):
	bl_label = "CheLive"

	def draw(self, context):
		layout = self.layout
		row = layout.row()
		row.operator("CheLiveExportMesh")
		row = layout.row()
		row.operator("CheLiveClose")

#compare two lists
def cmp(a, b):
	i = -1
	
	for x in a:
		i += 1
		
		if x != b[i]:
			return False
	
	return True

class Vertex:
	def __init__(self, c, n, v):
		self.coord = c[:]
		self.norm = n[:]
		self.vert = v[:]
	
	def compare(self, v):
		if cmp(self.coord, v.coord) and cmp(self.norm, v.norm) and cmp(self.vert, v.vert):
			return True
		
		return False

#export mesh operator
class OBJECT_OT_CheLiveExportMesh(bpy.types.Operator):
	bl_label = "Export mesh"
	bl_idname = "CheLiveExportMesh"
	bl_description = "Export mesh for CheLive"
	
	path = StringProperty(name="File Path", description="File path used for exporting the mesh for CheLive", maxlen=1024, default="mesh.mesh", subtype="FILENAME")
	filename = StringProperty(name="File Name", maxlen=256)
	directory = StringProperty(name="Directory", maxlen=1024)
	
	def execute(self, context):
		mesh = context.scene.objects.active.data
		
		if not mesh.active_uv_texture:
			print("There is no active UV texture!")
			return
		
		#non indexed vertices
		ni_verts = []
		i = 0
		
		for face in mesh.faces:
			uv = mesh.active_uv_texture.data[i].uv
			i += 1
			
			if len(face.verts) == 4:
				f = face.verts
				
				ni_verts.append(Vertex([uv[0][0], uv[0][1]], mesh.verts[f[0]].normal[:], mesh.verts[f[0]].co[:]))
				ni_verts.append(Vertex([uv[1][0], uv[1][1]], mesh.verts[f[1]].normal[:], mesh.verts[f[1]].co[:]))
				ni_verts.append(Vertex([uv[2][0], uv[2][1]], mesh.verts[f[2]].normal[:], mesh.verts[f[2]].co[:]))
				
				ni_verts.append(Vertex([uv[0][0], uv[0][1]], mesh.verts[f[0]].normal[:], mesh.verts[f[0]].co[:]))
				ni_verts.append(Vertex([uv[2][0], uv[2][1]], mesh.verts[f[2]].normal[:], mesh.verts[f[2]].co[:]))
				ni_verts.append(Vertex([uv[3][0], uv[3][1]], mesh.verts[f[3]].normal[:], mesh.verts[f[3]].co[:]))
			elif len(face.verts) == 3:
				f = face.verts
				
				ni_verts.append(Vertex([uv[0][0], uv[0][1]], mesh.verts[f[0]].normal[:], mesh.verts[f[0]].co[:]))
				ni_verts.append(Vertex([uv[1][0], uv[1][1]], mesh.verts[f[1]].normal[:], mesh.verts[f[1]].co[:]))
				ni_verts.append(Vertex([uv[2][0], uv[2][1]], mesh.verts[f[2]].normal[:], mesh.verts[f[2]].co[:]))
		
		#indexed verts
		verts = []
		indices = []
		
		for ni_vert in ni_verts:
			index = -1
			i = -1
			
			for vert in verts:
				i += 1
				
				if vert.compare(ni_vert):
					index = i
					break
			
			if index < 0:
				index = len(verts)
				verts.append(ni_vert)
			
			indices.append(index)
		
		print(str(len(ni_verts)) + ':' + str(len(verts)))
		
		try:
			f = open(self.properties.path, "wb")
			f.write(struct.pack('2i', len(verts), len(indices) // 3))
			
			for vert in verts:
				f.write(struct.pack('8f', 
					vert.coord[0], vert.coord[1], 
					vert.norm[0], vert.norm[1], vert.norm[2],
					vert.vert[0], vert.vert[1], vert.vert[2]
				))
			
			for index in indices:
				f.write(struct.pack('1H', index))
		finally:
			f.close()
		
		print('Mesh exported successfully');
		return{'FINISHED'}
	
	def invoke(self, context, event):
		if context.object.type.capitalize() != "Mesh":
			return
		
		context.manager.add_fileselect(self)
		return{'RUNNING_MODAL'}

#close operator
class OBJECT_OT_CheLiveClose(bpy.types.Operator):
	bl_label = "Close"
	bl_idname = "CheLiveClose"
	bl_description = "Close CheLive exporter"

	def invoke(self, context, event):
		bpy.types.unregister(OBJECT_OT_CheLiveClose)
		bpy.types.unregister(OBJECT_OT_CheLiveExportMesh)
		bpy.types.unregister(OBJECT_PT_CheLive)
		return{'FINISHED'}

bpy.types.register(OBJECT_PT_CheLive)
bpy.types.register(OBJECT_OT_CheLiveExportMesh)
bpy.types.register(OBJECT_OT_CheLiveClose)